// Q1_ThreadTest.cc 

/*
Nachos Project Stage1  
Soup and Salad
Assigned:	Wednesday, January 30, 2013
Due:		Friday, February 15, 2013
Description:
	Stage 1 is broken up into 7 parts. The first five parts are the
programs included in this file.
	This task is simply a simulation of a bunch of people shouting 
random phrases. The user will be prompted for the number of people 
shouting, X, and how many times each will shout, Y. So, each of the
X threads will shout Y times. All code can go in Q1_ThreadTest.cc.
	Implement the Dining Philosophers problem with semaphores.
All instructions and requirements from Task 2 apply, except that
 semaphores will not be used. In their place, you must use busy 
 waiting loops to wait for the chopsticks that a Q2_Philosopher needs.
 It is recommended to simply use an array of flags for this. Output 
 requirements are the same as Task 2.
	Implement the Dining Philosophers problem with semaphores.
All instructions and requirements from Task 2 apply, except that
 semaphores will not be used. In their place, you must use busy 
 waiting loops to wait for the chopsticks that a Q3_Philosopher needs.
 It is recommended to simply use an array of Q3_Flags for this. Output 
 requirements are the same as Task 2.
	Task 4 is a simulation of people visiting a post office. Each person is 
represented by a thread that can read its own mail, and then send mail out
to someone.
	Task 5 will extend the code of task 4 to include the use of semaphores for
any users waiting on another user's mailbox.
Author: John Judice & Nicholas J Sangchompuphen	
*/


#include "copyright.h"
#include "system.h"
#include "synch.h"
#include "string.h"

extern int *flag;		


// global variables
int Q1_TotalShout;						// total number of shouts 
int Q1_TotalShouter;					// total number of shouters
int Q1_Q1_ShoutGroupTotal = (Q1_TotalShout * Q1_TotalShouter);// total number of shout from all shouters
int Q1_ShoutGroup = 0;					// total number of shouts incremented
int *Q1_ShoutTotal;					// individual shout total


// This function will return a random statement
// when called
char*
SpeakArray(){
	//creating array of words for phrases.
	char * words[100];
	words[0] = "Fus Ro Dah!";
	words[1] = "Hello world";
	words[2] = "Tents are better. Fact.";
	words[3] = "It's the end of the world as we know it.";
	words[4] = "Nope.avi";
	//randomly choose the phase to use next
	int randomNumber2 = Random();
	randomNumber2 = randomNumber2 % 5;
	//return that phrase
	return words[randomNumber2];
}

// This function will get input from the screen
// and separate each character into an array
char* 
readInInput()
{
		char IntInInput;
		char *IntInputArray=new char[7];
		int intCount = 0;
		do{
		IntInInput = getchar();
		IntInputArray[intCount]=IntInInput;
		intCount +=1;
		}while(IntInInput != '\n');
		
		return &IntInputArray[0];
}

// This function will return a int number
// from an array of char
int 
catNumber(char * answer)
{	
	//variables for each char array 
    char str1[100];
	char str2[100];
	char str3[100];
	char str4[100];
	char str5[100];
	char str6[100];
	char str7[100];
	
	// change each char in to its digit
	for(int num4 = 0; num4 < 11;num4++){
	for(int num5 = 0; num5 < 6; num5++){
	if(answer[num5] == (48+num4)){
	answer[num5] = num4;};
	};
	};
	
	// concatenate the individual digits in the number
	int answer10;
	if((answer[0]) == 10){
		(sprintf(str1,"%d",answer[0]));
			answer10 = 0;}
	else if( answer[1] == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			answer10 = atoi(str1);}
	else if((answer[2]) == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			strcat(str1,str2);
			answer10 = atoi(str1);}
	else if((answer[3]) == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			(sprintf(str4,"%d",answer[3]));
			strcat(str1,str2);
			strcat(str1,str3);
			answer10 = atoi(str1);}
	else if(answer[4] == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			(sprintf(str4,"%d",answer[3]));
			(sprintf(str5,"%d",answer[4]));
			strcat(str1,str2);
			strcat(str1,str3);
			strcat(str1,str4);
			answer10 = atoi(str1);}
	else if(answer[5] == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			(sprintf(str4,"%d",answer[3]));
			(sprintf(str5,"%d",answer[4]));
			(sprintf(str6,"%d",answer[5]));
			strcat(str1,str2);
			strcat(str1,str3);
			strcat(str1,str4);
			strcat(str1,str5);
			answer10 = atoi(str1);}
	else if(answer[6] == 10){
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			(sprintf(str4,"%d",answer[3]));
			(sprintf(str5,"%d",answer[4]));
			(sprintf(str6,"%d",answer[5]));
			(sprintf(str7,"%d",answer[6]));
			strcat(str1,str2);
			strcat(str1,str3);
			strcat(str1,str4);
			strcat(str1,str5);
			strcat(str1,str6);
			answer10 = atoi(str1);}
	else{
			(sprintf(str1,"%d",answer[0]));
			(sprintf(str2,"%d",answer[1]));
			(sprintf(str3,"%d",answer[2]));
			(sprintf(str4,"%d",answer[3]));
			(sprintf(str5,"%d",answer[4]));
			(sprintf(str6,"%d",answer[5]));
			(sprintf(str7,"%d",answer[6]));
			strcat(str1,str2);
			strcat(str1,str3);
			strcat(str1,str4);
			strcat(str1,str5);
			strcat(str1,str6);
			strcat(str1,str7);
			answer10 = atoi(str1);
	};
	return answer10  ;
}

// This function will request the number of shouters
// from the user and verify that it is a digit that
// is between 0 and 1000. Any other input will get 
// an error message		
void
Q1_getNumOfShouters()
{
	int concatAnswer;
	bool test = true;
	char *answer = new char[7];
	do
	{
		test = true;
		printf("How many people will be shouting :");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q1_TotalShouter = concatAnswer;
};

// This function will request the number of shouts per shouter
// from the user and verify that it is a digit that
// is between 0 and 1000. Any other input will get 
// an error message	
void
Q1_getNumOfShouts()	
{
	int concatAnswer;
	bool test = true;
	char *answer = new char[7];
	do
	{
		test = true;
		printf("How many times will they shout :");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q1_TotalShout = concatAnswer;
};

// This function will simulate work for the shouter
// The thread will run through a busy wait loop
// till the random number of loops is done.
void
Q1_workTast()
{
	int randomNumber = Random();
	randomNumber = randomNumber % 5;
	int num = 0;

	while(num < randomNumber)
	{
		if(Q1_ShoutGroup < Q1_Q1_ShoutGroupTotal)
		{
			num = randomNumber;
		};
		currentThread->Yield();
		num++;
	};
};

// This function will run the shouter through their
// process of shouting the phrase and working. 
void
Q1_shoutThread(int which)
{
	for(int i =0; i<Q1_TotalShout; i++)
	{
		printf("Shouter %d:", which);
		printf("%s \n",SpeakArray());
		Q1_ShoutTotal[which]++;
		Q1_ShoutGroup++;
		Q1_workTast();
	};
};

// This function will create the number of threads
// need to be used as shouters.
void
Q1_createThreads()
{
	Q1_ShoutGroup = 0;
	Q1_ShoutTotal = new int[Q1_TotalShouter+1];
	for(int i = 0; i < Q1_TotalShouter; i++)
	{
		Q1_ShoutTotal[i] = 0;
	};
	for(int num = 0;num < Q1_TotalShouter;num++){
	Thread *t = new Thread("Shouting person");
	// making the thread run
	t->Fork(Q1_shoutThread,num);
	};

};



// This function will start by calling a function
// that will get the number of shouters. Next it will
// call a function that will call a function that 
// will get the number of shouts. Followed by the 
// function that will create the threads. 
// Finally it will call that function that will 
// start the process of the looping of shouting
// and waiting.
void
Q1_ThreadTest()
{
	Q1_getNumOfShouters();
	Q1_getNumOfShouts();
	Q1_createThreads();

};
// Q2_ThreadTest.cc 
/*
Nachos Project Stage1  Task 2
Soup and Salad
Assigned:	Wednesday, January 30, 2013
Due:		Friday, February 15, 2013
Description:
	Implement the Dining Q2_Philosophers problem with semaphores.
All instructions and requirements from Task 2 apply, except that
 semaphores will not be used. In their place, you must use busy 
 waiting loops to wait for the chopsticks that a Q2_Philosopher needs.
 It is recommended to simply use an array of flags for this. Output 
 requirements are the same as Task 2.
Author: John Judice & Nicholas J Sangchompuphen	
*/

//global variables
int Q2_PhilNum;				//number of Q2_Philosophers
int Q2_totalNumMeals;			//total number of meals
int Q2_totalEaten;				//number of meals eaten increment
bool Q2_testEnter;				// bool used in Q2_PhilosopherSit()
Semaphore **Q2_mySemaphores;
int Q2_count = 0;				// variable used in Q2_PhilosopherSit()
int Q2_doneCount;				// variable used to add up all done Q2_Philosophers

// struct for Q2_Philosopher used to establish if
// they are eating, thinking, or entering with 1 or 0
struct Q2_Philosopher{
 int eating;				// 0 or 1 represent eating status
 int thinking;				// 0 or 1 represent thinking status
 int enter;					// 0 or 1 represent join table
 int done;					// 0 or 1 represent done eating
};
Q2_Philosopher *Q2_Phil;			// array of struct


//use to get a random number between 2 and 5
int
Q2_RandomCall(){
	// initialize random variable
	int randomNumber;
	// call random number between 2 and 5
	randomNumber = (Random())%3 +2;
	return randomNumber;
}

// This function will get from the number of Q2_Philosophers
// used in this program.
void
Q2_getNumOfPhilosopher()
{
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				//bool used to test valid number
	char *answer = new char[7];		//char used for return from catNumber()
	// opening print
	printf("Welcome to Cafe Des Nachos!!!\n\n");
	do{
		
		test = true;
		printf("How many Philosophers will be dining this evening?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q2_PhilNum = concatAnswer;				//set global variable for total Q2_Philosophers
};

// Function will get the number of meals used in this
// program.
void
Q2_getNumOfMeal(){
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	do
	{
		test = true;
		printf("\nHow many meals do we have to offer?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q2_totalNumMeals = concatAnswer;			//set global variable for total meals
};

// Function used print when each Q2_Philosopher has
// joined the table
void
Q2_PhilosopherSit(int which)
{
	printf("Philosopher %d has joined the table.\n",which);
	Q2_Phil[which].enter = 1;
	//check if all Q2_Philosophers have entered to print message
	Q2_count = Q2_count + Q2_Phil[which].enter;
	// allow the next Q2_Philosopher to enter
	
	while(Q2_count <  Q2_PhilNum)
	{
		currentThread->Yield();
	};
	if((Q2_count == Q2_PhilNum) &&(Q2_testEnter == false)){
	printf("All Philosophers are now seated.\n\n");
	Q2_testEnter = true;
	};
};

// Function used to check that all Q2_Philosophers are done before they
// leave the table
void
Q2_checkAllDone(int which)
{
	Q2_Phil[which].done = 1;
	Q2_doneCount = Q2_doneCount + Q2_Phil[which].done;
	// allow the next Q2_Philosopher to enter
	while(Q2_doneCount < Q2_PhilNum)
	{
		currentThread->Yield();
	};
};

// Function used to simulate a Q2_Philosopher putting down their
// fork and starting to think
void
Q2_PhilosopherThinks(int which)
{
	Q2_mySemaphores[which]->V();
	printf("	Philosopher %d drops his left chopstick (#%d).\n",which,which);
	Q2_mySemaphores[((which+1)%Q2_PhilNum)]->V();
	printf("	Philosopher %d drops his right chopstick (#%d).\n\n",which,(which+1)%Q2_PhilNum);
	printf("Philosopher %d started pondering the mysteries of the universe.\n\n",which);
	if(Q2_totalEaten <Q2_totalNumMeals)
	{
		
	// loop through thinking time and set Q2_Philosopher as thinking
	Q2_Phil[which].thinking = 1;
	int Wait =(Random()%3 +2); 
	while (Wait > 0){
		Wait--;
		currentThread->Yield();
	};
	// set Q2_Philosopher as finished eating
	Q2_Phil[which].thinking = 0;
	};
};

// Function used to simulate a Q2_Philosopher picking up fork and
// eating meal
void
Q2_PhilosopherEat(int which)
{
	while((Q2_Phil[(which+Q2_PhilNum-1)%Q2_PhilNum].eating) == 1)
	{
		currentThread->Yield();
	};
	// using semaphores for the chopsticks to pick up
	Q2_mySemaphores[which]->P();
	printf("	Philosopher %d picks up his left chopstick (#%d).\n",which,which);
	while((Q2_Phil[(which+1)%Q2_PhilNum].eating) == 1)
	{
		currentThread->Yield();
	};
	//checking for the total of times the Q2_Philosophers have eaten compared to
	//the total meals given my user, if equal then skip picking up chopsticks

	Q2_mySemaphores[(which+1)%Q2_PhilNum]->P();
	printf("	Philosopher %d picks up his right chopstick (#%d).\n\n",which,(which+1)%Q2_PhilNum);
	
	// set the Q2_Philosopher as eating
	
	if(Q2_totalEaten < Q2_totalNumMeals)
	{
	printf("Philosopher %d started eating his dinner.\n\n",which);	
	Q2_Phil[which].eating = 1;
	Q2_totalEaten++;

	
	printf("(%d Philosophers has eaten so far)\n\n",Q2_totalEaten);
	
	// the Q2_Philosopher loops through eating time
	//test = false;
	//
	int Wait =(Random()%3 +2); 
	while (Wait > 0){
		Wait--;
		currentThread->Yield();
	};
	// set Q2_Philosopher as finished eating
	Q2_Phil[which].eating = 0;
	};
};


// Function used to print out which Q2_Philosopher has left the table
void
Q2_PhilosopherLeaves(int which)
{
	//exit print out
	printf("Philosopher %d has left the table, there were no meals left!\n",which);
};

// Function used to loop through the steps used for a 
// Q2_Philosopher to sit eat and think
void
Q2_PhilThread(int which)
{
	Q2_PhilosopherSit(which);
	if(Q2_PhilNum == 1)
	{
		printf("Philosopher %d cannot eat with only one chopstick\n",which);
	}
	else
	{
		while(Q2_totalEaten < Q2_totalNumMeals)
		{
			Q2_PhilosopherEat(which);
			Q2_PhilosopherThinks(which);
		};
	};
	Q2_checkAllDone(which);
	Q2_PhilosopherLeaves(which);
};

// Function used to create the threats used to simulate
// each Q2_Philosopher in the program.
void
Q2_createThreads()
{
	Q2_mySemaphores = new Semaphore*[Q2_PhilNum];
	for(int NumSemaphore=0;NumSemaphore<Q2_PhilNum;NumSemaphore++)
	{
		Q2_mySemaphores[NumSemaphore]= new Semaphore("Chopstick",1);
	};
	
	// set bool for Q2_Philosophers entry
	Q2_testEnter = false;
	// assign for global variable
	
	Q2_Phil = new Q2_Philosopher[Q2_PhilNum];
	for(int num = 0;num < Q2_PhilNum;num++)
	{
		Thread *t = new Thread("Philosopher");
		// making the thread run
		t->Fork(Q2_PhilThread,num);
		Q2_Phil[num].enter = 0;
		Q2_Phil[num].eating = 0;
	    Q2_Phil[num].thinking = 0;
		Q2_Phil[num].done = 0;
	};
	
};



// Function will call the functions needed for 
// the dining Q2_Philosophers simulation to take place
void
Q2_ThreadTest()
{
	Q2_getNumOfPhilosopher();
	Q2_getNumOfMeal();
	Q2_createThreads();
};

//global variables
int Q3_PhilNum;				//number of Q3_Philosophers
int Q3_totalNumMeals;			//total number of meals
int Q3_totalEaten;				//number of meals eaten increment
bool Q3_testEnter;				// bool used in Q3_PhilosopherSit()
int *Q3_Flag;					// array used for semaphores
int Q3_count = 0;				// variable used in Q3_PhilosopherSit()
int Q3_doneCount;				// variable used to add up all done Q3_Philosophers


// struct for Q3_Philosopher used to establish if
// they are eating, thinking, or entering with 1 or 0
struct Q3_Philosopher{
 int eating;				// 0 or 1 represent eating status
 int thinking;				// 0 or 1 represent thinking status
 int enter;					// 0 or 1 represent join table
 int done;					// 0 or 1 represent done eating
};
Q3_Philosopher *Q3_Phil;			// array of struct


//use to get a random number between 2 and 5
int
Q3_RandomCall(){
	// initialize random variable
	int randomNumber;
	// call random number between 2 and 5
	randomNumber = (Random())%3 +2;
	return randomNumber;
}



void
Q3_getNumOfPhilosopher()
{
	// variables
	int concatAnswer;				//concatenated answer		
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	// opening print
	printf("Welcome to Cafe Des Nachos!!!\n\n");
	do{
		test = true;
		printf("How many Philosophers will be dining this evening?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q3_PhilNum = concatAnswer;			//set global variable for total Q3_Philosophers
};

// Function will get the number of meals used in this
// program.
void
Q3_getNumOfMeal(){
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	do
	{
		test = true;
		printf("\nHow many meals do we have to offer?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	Q3_totalNumMeals = concatAnswer;		// set global variable for total meals
};

// Function used print when each Q3_Philosopher has
// joined the table
void
Q3_PhilosopherSit(int which)
{
	printf("Philosopher %d has joined the table.\n",which);
	Q3_Phil[which].enter = 1;
	//check if all Q3_Philosophers have entered to print message
	Q3_count = Q3_count + Q3_Phil[which].enter;
	while(Q3_count < Q3_PhilNum)
	{
		// allow the next Q3_Philosopher to enter
		currentThread->Yield();
	};
	if((Q3_count == Q3_PhilNum) &&(Q3_testEnter == false)){
	printf("All Philosophers are now seated.\n\n");
	Q3_testEnter = true;
	};
};

// Function used to check that all Q3_Philosophers are done before they
// leave the table
void
Q3_checkAllDone(int which)
{
	Q3_Phil[which].done = 1;
	Q3_doneCount = Q3_doneCount + Q3_Phil[which].done;
	// allow the next Q3_Philosopher to enter
	while(Q3_doneCount < Q3_PhilNum)
	{
		currentThread->Yield();
	};
};

// Function used to simulate a Q3_Philosopher putting down their
// fork and starting to think
void
Q3_PhilosopherThinks(int which)
{
	Q3_Flag[which] = 0;
	printf("	Philosopher %d drops his left chopstick (#%d).\n",which,which);
	Q3_Flag[(which+1)%Q3_PhilNum] = 1;
	printf("	Philosopher %d drops his right chopstick (#%d).\n\n",which,(which+1)%Q3_PhilNum);
	printf("Philosopher %d started pondering the mysteries of the universe.\n\n",which);
	if(Q3_totalEaten <Q3_totalNumMeals)
	{
	// loop through thinking time and set Q3_Philosopher as thinking
	Q3_Phil[which].thinking = 1;
	int Wait =(Random()%3 +2); 
	while (Wait > 0){
		Wait--;
		currentThread->Yield();
	};
	// set Q3_Philosopher as finished eating
	Q3_Phil[which].thinking = 0;
	};
};

// Function used to simulate a Q3_Philosopher picking up fork and
// eating meal
void
Q3_PhilosopherEat(int which)
{
	while((Q3_Phil[(which+Q3_PhilNum-1)%Q3_PhilNum].eating) == 1)
	{
		currentThread->Yield();
	};
	// using semaphores for the chopsticks to pick up
	Q3_Flag[which] = 1;
	printf("	Philosopher %d picks up his left chopstick (#%d).\n",which,which);
	while((Q3_Phil[(which+1)%Q3_PhilNum].eating) == 1)
	{
		currentThread->Yield();
	};
	//checking for the total of times the Q3_Philosophers have eaten compared to
	//the total meals given my user, if equal then skip picking up chopsticks
	//if(Q3_totalEaten < Q3_totalNumMeals){
	Q3_Flag[(which+1)%Q3_PhilNum] = 1;
	printf("	Philosopher %d picks up his right chopstick (#%d).\n\n",which,(which+1)%Q3_PhilNum);
	// set the Q3_Philosopher as eating
	if(Q3_totalEaten < Q3_totalNumMeals)
	{
	printf("Philosopher %d started eating his dinner.\n\n",which);	
	Q3_Phil[which].eating = 1;
	Q3_totalEaten++;
	printf("(%d Philosophers has eaten so far)\n\n",Q3_totalEaten);
	// the Q3_Philosopher loops through eating time
	int Wait =(Random()%3 +2); 
	while (Wait > 0){
		Wait--;
		currentThread->Yield();
	};
	// set Q3_Philosopher as finished eating
	Q3_Phil[which].eating = 0;
	};
};

// Function used to print out which Q3_Philosopher has left the table
void
Q3_PhilosopherLeaves(int which)
{
	//exit print out
	printf("Philosopher %d has left the table, there were no meals left!\n",which);
};

// Function used to loop through the steps used for a 
// Q3_Philosopher to sit eat and think
void
Q3_PhilThread(int which)
{
	Q3_PhilosopherSit(which);
	if(Q3_PhilNum == 1)
	{
		printf("Philosopher %d cannot eat with only one chopstick\n",which);
	}
	else
	{
		while(Q3_totalEaten < Q3_totalNumMeals)
		{
			Q3_PhilosopherEat(which);
			Q3_PhilosopherThinks(which);
		};
	};
	Q3_checkAllDone(which);
	Q3_PhilosopherLeaves(which);
};

// Function used to create the threats used to simulate
// each Q3_Philosopher in the program.
void
Q3_createThreads()
{
	// set bool for Q3_Philosophers entry
	Q3_testEnter = false;
	// assign for global variable
	Q3_Flag = new int[Q3_PhilNum];
	Q3_Phil = new Q3_Philosopher[Q3_PhilNum];
	for(int num = 0;num < Q3_PhilNum;num++)
	{
		Thread *t = new Thread("Q3_Philosopher");
		// making the thread run
		t->Fork(Q3_PhilThread,num);
		Q3_Phil[num].enter = 0;
		Q3_Phil[num].eating = 0;
	    Q3_Phil[num].thinking = 0;
		Q3_Phil[num].done = 0;
		Q3_Flag[num] = 0;
	};

};



// Function will call the functions needed for 
// the dining Q3_Philosophers simulation to take place
void
Q3_ThreadTest()
{
	Q3_getNumOfPhilosopher();
	Q3_getNumOfMeal();
	Q3_createThreads();

};



//program 4 and 5
struct Q5_msg
{
	/* Since the grid of mailQ5_boxes is a 2D array. The to and from fields will be filled with the appropriate index." */
	int* box_num;
	int* from;
	int* to;
	char* content;
};
int * Q5_inSemaphore;
int Q5_countBreakOut;
bool Q5_lockBreakOut;
int Q5_temp;
// Q5_doneCheck used to see that everyone done so they can exit at same time.
int* Q5_doneCheck;
// Q5_Flag array is used to check if the first try to deliver mail is 
// successful or not
int *Q5_Flag;
// Q5_WFlag array is used when to stop everyone from working and start reading
// this array is used to prevent deadlock
int *Q5_WFlag;
//count used in figuring out when everyone is done
int Q5_groupDoneCount;
int *Q5_busy = new int;
int* Q5_sent_msgs = new int; // total message counter
int* Q5_choice = new int;
Semaphore* Q5_MailBoxSem;
Semaphore** Q5_BoxGuard;
char *Q5_words[100];
Q5_msg** Q5_boxes;
int* Q5_numBoxes = new int; //total number of mailQ5_boxes
int* Q5_box_capacity = new int; //maximum number of messages a box can contain at once
char *Q5_chInputArray = new char[7]; // array used to check input
int *Q5_msg_limit = new int; //total message limit


int
Q5_Test(int dest) //Q5_Tests if mailbox is full
{
	int count = 0;
	for (int j=0; j<*Q5_box_capacity; j++)
	{
		//printf("Contents of box %d slot %d are To: %d , From: %d, %s. \n", dest, j, *Q5_boxes[dest][j].to, *Q5_boxes[dest][j].from, Q5_boxes[dest][j].content);
		if((*Q5_boxes[dest][j].to != -1) && (*Q5_boxes[dest][j].from != -1) && (Q5_boxes[dest][j].content != "Empty"))
		{
			//printf("Incrementing Count. \n");
			count = count + 1;
		};
	};
	return count;
}

int 
Q5_nextDest(int dest)
{
	int c;
	for (int j=0; j<*Q5_numBoxes; j++)
	{
		if (*Q5_boxes[dest][j].to == -1 && *Q5_boxes[dest][j].from == -1 && Q5_boxes[dest][j].content == "Empty")
		{
			c = j;
			break;
		}
	}
	return c;
}

void
Q5_PersonLeaves(int which)
{
	printf("Person %d is leaving the post office. \n", which);
}

void 
Q5_Kill(int c)
{
	// since limit has been reached, release all Q5_MailBoxSem semaphores
	for(int i = 0;i<*Q5_numBoxes;i++)
	{
		Q5_MailBoxSem->V();
	};
		// release all Q5_BoxGuard semaphores
		for(int i = 0;i<*Q5_numBoxes;i++)
	{
		Q5_BoxGuard[i]->V();
	};
	Q5_doneCheck[c] = 1;
	Q5_groupDoneCount = (Q5_groupDoneCount + Q5_doneCheck[c]);
	while(Q5_groupDoneCount < *Q5_numBoxes)
	{
		currentThread->Yield();
	};
}


void
Q5_Work(int which)
{
	if (*Q5_sent_msgs < *Q5_msg_limit)
	{
		int checks = 0;
		int c_num = (Random() % 5 + 1);
		Q5_WFlag[which] = 1;
		while ((checks < c_num) && (Q5_WFlag[which] == 1)) //Wait x turns before reading again
		{
			currentThread->Yield();
			//printf("stuck in work loop line 1029 person %d==============\n",which);
			checks = checks + 1;
			if (*Q5_sent_msgs == *Q5_msg_limit)
			{
				Q5_Work(which);
			};
		};
		Q5_WFlag[which] = 0;
		checks = 0;
	};
}

void 
Q5_Read(int place)
{
	if (*Q5_sent_msgs < *Q5_msg_limit)
	{
		int count = 0;
		printf("\nPerson %d is checking his mail. \n", place);
		count = Q5_Test(place);
		printf("	The number of messages present in box %d is %d. \n", place, count);
		for (int i=0; i<*Q5_box_capacity; i++)
		{
			Q5_MailBoxSem->P();
			// if the limit is reached during the loop, then send the thread
			// to the work function, where it will go to the kill function and
			// finally to the personleaves function.
			if (*Q5_sent_msgs < *Q5_msg_limit)
			{
				count = Q5_Test(place);
				if ((count > 1)&&(*Q5_boxes[place][i].from >=0))
				{
					printf("Person %d is reading the message from person %d Content: %s.\n", place, *Q5_boxes[place][i].from, Q5_boxes[place][i].content);
					*Q5_boxes[place][i].from = -1;
					*Q5_boxes[place][i].to = -1;
					Q5_boxes[place][i].content = "Empty";
					count--;
					printf("	next person is allowed to check their mailbox\n");
					Q5_MailBoxSem->V();
					if (*Q5_choice == 5)
					{
						Q5_BoxGuard[place]->V();
					}
					currentThread->Yield();
				}
				else if((count == 1)&&(*Q5_boxes[place][i].from >=0))
				{	
					count = Q5_Test(place);
					if(count == 1)
					{
						printf("Person %d is reading the message from person %d Content: %s.  line 1079\n", place, *Q5_boxes[place][i].from, Q5_boxes[place][i].content);
						*Q5_boxes[place][i].from = -1;
						*Q5_boxes[place][i].to = -1;
						Q5_boxes[place][i].content = "Empty";
						count--;
						if (*Q5_choice == 5)
						{
						Q5_BoxGuard[place]->V();
						}
						Q5_MailBoxSem->V();
						currentThread->Yield();
					}
					else
					{
						Q5_MailBoxSem->V();
					};
				};
				//else
				//{
				//	Q5_MailBoxSem->V();
				//};
				
				
			};
			Q5_MailBoxSem->V();
			
		};
	};
}

void 
Q5_Write(int sender)
{
	if (*Q5_sent_msgs < *Q5_msg_limit)
	{
		int dest;
		int count = 0;
		int index = (Random() % 5);
		if(*Q5_numBoxes == 2)
		{
			if(sender == 1)
			{
				dest = 0;
			}
			else{
				dest = 1;
			}; 
		}
		else
		{
			do{
				dest = (Random() % *Q5_numBoxes);
			}while((dest == sender) || (dest == Q5_temp)) ;
		};
		// First step in preventing deadlocks. Making sure the random counter does not pick the same 
		// destination twice in a roll
		Q5_temp = dest;
		count = Q5_Test(dest);
		// Second step in preventing deadlocks. if statement used to catch if the destination box is full.
		// By comparing the count to *Q5_box_capacity the person is trying to mail letter. This point is 
		// considered the first atQ5_tempt to mail letter
		if (*Q5_choice == 5)
		{
			//If running options for task five, check the semaphore for the recipients mailbox check to
		    //prevent dead locks with Q5_BoxGuard semaphore. if all threads are in semaphores, release the 
			//semaphores and call the Q5_Work function with that thread.
			Q5_inSemaphore[sender] = 1;
			Q5_countBreakOut = Q5_countBreakOut + Q5_inSemaphore[sender];
			if(Q5_countBreakOut == *Q5_numBoxes)
			{
				// if statement for preventing deadlocks the Q5_lockBreakOut bool is set to true,
				// and all Q5_BoxGuards set are released.
				Q5_lockBreakOut = true;
				for(int i = 0;i<*Q5_numBoxes;i++)
				{
					Q5_BoxGuard[i]->V();
				};
			};
			Q5_BoxGuard[dest]->P();
			//printf(" %d is free to place mail for %d \n",sender,dest);
			// the Q5_countBreakOut is reset to zero
			Q5_countBreakOut = Q5_countBreakOut - 1;
			// Q5_inSemaphore is reset to 0
			Q5_inSemaphore[sender] = 0;
			// conditions are checked to make sure that the 
			// limit was not reached during last semaphore
			if (*Q5_sent_msgs == *Q5_msg_limit)
			{
				Q5_Work(sender);
			};
			// if Q5_lockBreakOut was set to true then send the thread to 
			// the read function and reset the Q5_lockBreakOut bool.
			if(Q5_lockBreakOut == true)
			{
				Q5_lockBreakOut = false;
				Q5_Read(sender);
			};
		};
		if(count == *Q5_box_capacity)
		{
			printf("	Destination Mailbox is full; Waiting. \n");
			// Q5_Flag used in checking for one second try  to deliver
			// before throwing out mail
			while ((count == *Q5_box_capacity) && (Q5_Flag[sender] == 0))
			{
				currentThread->Yield();
				count = Q5_Test(dest);
				// Q5_Flag will be set to 1 after the first trip through the loop.
				Q5_Flag[sender] = 1;
				// if the limit is reached during the loop, then send the thread to the work function, 
				// where it will go to the kill function and finally to the personleaves function.
				if (*Q5_sent_msgs == *Q5_msg_limit)
				{
					Q5_Work(sender);
				};
			};
			// Since the mail has been checked more than once, the letter is thrown away. This is the
			// first step to prevent deadlocks.
			printf("Person %d has tried more than once to mail to %d failed.\n	Throwing %d mail away. \n",sender,dest,dest);
			// The third step in preventing deadlocks is for everyone that is in the working loop at the
			// time that mail is being thrown away are released to start reading their mail.
			for(int ix =0;ix<*Q5_numBoxes;ix++)
			{
				Q5_WFlag[ix] = 0;
			};
			// the person who throw out their mail will now proceed to 
			// the read function and their Q5_Flag will be reset to 0.
			if(Q5_Flag[sender] == 1)
			{
				Q5_Flag[sender] = 0;
				Q5_Read(sender);
			};
		}
		else if (*Q5_sent_msgs < *Q5_msg_limit)
		{
			//printf(" %d is in Q5_MailBoxSem->P() \n",sender);
			Q5_MailBoxSem->P();
			// Checking when a thread comes out of the Q5_MailBoxSem to see that the limit has not
			//been reached. if it has send the thread to work, where
			// it will go the end of the program.
			if (*Q5_sent_msgs == *Q5_msg_limit)
			{
				Q5_Work(sender);
			};
			// if statement used to check if sent messages has not equaled message limit since the sender
			// entered the Q5_MailBoxSem->P() loop
			if (*Q5_sent_msgs < *Q5_msg_limit)
			{
				// if statement used to catch if the destination box is full after the sender comes out 
				// of the Q5_MailBoxSem->P()	loop. By comparing the count to *Q5_box_capacity the person is trying to mail 
				// letter. the mail has tried to be delivered at least once at this time.
				count = Q5_Test(dest);
				if(count == *Q5_box_capacity) 
				{
					printf("Person %d has tried more than once to mail to %d failed.\n 	Throwing %d mail away \n",sender,dest,dest);
				}	
				else if(count < *Q5_box_capacity)
				{
					printf("Person %d is writing mail to person %d. \n", sender, dest);
					++(*Q5_sent_msgs);
					printf("	%d messages in total have been sent. \n", *Q5_sent_msgs);
					int box = Q5_nextDest(dest);
					index = (Random() % 5);
					*Q5_boxes[dest][box].to = dest;
					*Q5_boxes[dest][box].from = sender;
					Q5_boxes[dest][box].content = Q5_words[index];
				};
				
			};
			Q5_MailBoxSem->V();
		};
	};

}


void
Q5_getNumOfMailBoxes(){
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	do
	{
		test = true;
		printf("\n");
		printf("How many mail boxes are there? ");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	*Q5_numBoxes = concatAnswer;		// set global variable for total meals
}

void
Q5_getNumOfMailboxCapacity(){
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	do
	{
		test = true;
		printf("\n");
		printf("What is the capacity of each mailbox?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);
	*Q5_box_capacity = concatAnswer;		// set global variable for total meals
}


void
Q5_getMessageLimit(){
	// variables
	int concatAnswer;				//concatenated answer
	bool test = true;				// bool used to test valid number
	char *answer = new char[7];		// char used for return from catNumber()
	do
	{
		test = true;
		printf("\n");
		printf("What is the message limit?");
		// collect the input as an array of 4 char
		answer = readInInput();
		// check each char is in the right range to be converted to digit
		for(int num6 = 0;num6 <7;num6++)
		{
			if((48 > answer[num6]) && (answer[num6] != 10) && (answer[num6] != 0))
			{
				test = false;
			};
			if (answer[num6] > 57)
			{
				test = false;
			};
		};	
		concatAnswer = catNumber(answer);
		if(concatAnswer == 0)
		{
			test = false;
		};
		
		if(test == false)
		{
			printf("error invalid input\n");
		};
	}while(test == false);

	*Q5_msg_limit = concatAnswer;		// set global variable for total meals
}

void
Q5_mailBoxThread(int which)
{
	if(*Q5_numBoxes == 1)
	{
		printf("Person %d cannot mail to himself \n",which);
	}
	else
	{
		while(*Q5_sent_msgs < *Q5_msg_limit)
		{
			//printf("\n");
			//printf(" intering read person %d ============================================\n",which);
			Q5_Read(which);
			//printf("\n");
			//printf(" intering write person %d ============================================\n",which);
		
			Q5_Write(which);
			//printf("\n");
			//printf(" intering work person %d ============================================\n",which);
		
			Q5_Work(which);
		};
	};
	//printf(" intering kill person %d ============================================\n",which);
		
	Q5_Kill(which);
	Q5_PersonLeaves(which);
}
void
Q5_startSimulation()
{
	*Q5_sent_msgs = 0;
	*Q5_choice = 5;
	Q5_MailBoxSem = new Semaphore("Postman", 1);
	Q5_BoxGuard = new Semaphore*[*Q5_numBoxes];
	if (*Q5_choice == 5)
	{
		for (int i=0; i<*Q5_numBoxes; i++)
		{
			Q5_BoxGuard[i] = new Semaphore("Guard", *Q5_box_capacity);
		}
	}
	Q5_words[0] = "Eclair";
	Q5_words[1] = "Cotton Candy";
	Q5_words[2] = "Candy Cane";
	Q5_words[3] = "Oatmeal Cookie";
	Q5_words[4] = "Pop-Tart";
	int c = 0;
	c = 0;
	Q5_doneCheck = new int[*Q5_numBoxes];
	Q5_temp = 0;
	Q5_countBreakOut = 0;
	Q5_inSemaphore = new int[*Q5_numBoxes];
	Q5_Flag = new int[*Q5_numBoxes];
	Q5_WFlag = new int[*Q5_numBoxes];
	Q5_boxes = new Q5_msg*[*Q5_numBoxes];
	Q5_groupDoneCount = 0;
	Q5_lockBreakOut = false;
	delete [] Q5_chInputArray; 
	Q5_chInputArray = new char[5];
	for (int a=0; a<*Q5_numBoxes; a++)
	{
		Q5_boxes[a] = new Q5_msg[*Q5_box_capacity];
		for (int b=0; b<*Q5_box_capacity; b++)
		{
			Q5_boxes[a][b].to = new int;
			Q5_boxes[a][b].from = new int;
			*Q5_boxes[a][b].to = -1;
			*Q5_boxes[a][b].from = -1;
			Q5_boxes[a][b].content = "Empty";
		}
	};
	for (int x=0; x<*Q5_numBoxes; x++)
	{
		Thread *t = new Thread("mailBoxThread");
		printf("Creating new thread \n");
		Q5_Flag[x] = 0;
		Q5_WFlag[x] = 0;
		Q5_doneCheck[x] = 0;
		Q5_inSemaphore[x] = 0;
		t->Fork(Q5_mailBoxThread,x);
	}; 

} 


void
Q5_ThreadTest()
{
	Q5_getMessageLimit();
	Q5_getNumOfMailboxCapacity();
	Q5_getNumOfMailBoxes();
	Q5_startSimulation();
}

// check the global variable to decide which file to run
void
ThreadTest()
{
	switch(*flag)
	{
	case 1:
		Q1_ThreadTest();
		break;
	case 2:
		Q2_ThreadTest();
		break;
	case 3:
		Q3_ThreadTest();
		break;
	case 4:
		*Q5_choice = 4;
		Q5_ThreadTest();
		break;
	default:
		*Q5_choice = 5;
		Q5_ThreadTest();
	
	};

};




